package org.spindle.soasuite.controllers;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ArrayNode;
import org.spindle.soasuite.core.api.AExecutable;
import org.spindle.soasuite.core.api.annotations.Executable;
import org.spindle.soasuite.core.api.annotations.Parameter;
import org.spindle.soasuite.core.constants.EntityConstants;
import org.spindle.soasuite.core.constants.ProjectConstants;
import org.spindle.soasuite.core.constants.StateCodes;
import org.spindle.soasuite.core.constants.StateConstants;
import org.spindle.soasuite.core.logging.Log;
import org.spindle.soasuite.core.logging.LogFactory;
import org.spindle.soasuite.data.internal.Configuration;
import org.spindle.soasuite.data.internal.MockService;
import org.spindle.soasuite.data.internal.Project;
import org.spindle.soasuite.data.internal.User;
import org.spindle.soasuite.parser.ParserFactory;
import org.spindle.soasuite.parser.api.IParser;
import org.spindle.soasuite.parser.api.ParserConstants;

import java.util.*;

@Executable(path = "/project")
class ProjectController extends AExecutable {

    private static Log log = LogFactory.getLogger(ProjectController.class);

    @Parameter(name = "method")
    private String method;

    @Parameter(name = "projectName")
    private String projectName;

    @Parameter(name = "endpoint")
    private String endpoint;

    @Parameter(name = "type")
    private String type;

    @Parameter(name = "jsonConfiguration")
    private String jsonConfiguration;

    @Override
    public Object execute() {


        Integer userId = (Integer) getStateObject("userId");

        log.logDebug("UserId: " + userId + " method: " + method + " projectName: " + projectName);
        User user = (User) getStateObject(StateConstants.USER);
        //getInternalDatasource().refresh(user);

        Project selectedProject = null;

        if (projectName != null) {
            for (Project proj : user.getProjects()) {
                if (proj.getProjectName().equals(projectName)) {
                    selectedProject = proj;

                }
            }
        }

        if (method.equals("getAllProjects")) {
            for (Project project : user.getProjects()) {
                addReturnParameter(ProjectConstants.PROJECT_PREFIX + project.getId(), project.getProjectName());
            }

        } else if ("addProject".equals(method)) {
            Boolean valid = true;
            for (Project project : user.getProjects()) {
                if (project.getProjectName().equals(projectName)) {
                    valid = false;
                    addReturnParameter(StateConstants.EXECUTION_CODE, StateCodes.PROJECT_NAME_ALREADY_EXIST);
                }
            }

            if (valid) {
                Project project = new Project();
                project.setProjectName(projectName);

                user.addProject(project);

                getInternalDatasource().persist(project);
                addReturnParameter(StateConstants.EXECUTION_CODE, StateCodes.OPERATION_SUCESFULL);
                addReturnParameter(EntityConstants.ENTITY_ID, ProjectConstants.PROJECT_PREFIX + project.getId());
            }
        } else if ("addEndpoint".equals(method)) {
            log.logDebug("Endpoint: " + endpoint);
            log.logDebug("Type: " + type);
            log.logDebug("jsonConfiguration: " + jsonConfiguration);

            ///System.out.println(root.get(0).get("jsonConfig"));


            if (selectedProject != null) {
                MockService service = new MockService();
                service.setEndpoint(endpoint);
                service.setType(type);
                service.setProject(selectedProject);

                IParser parser = ParserFactory.getParser(ParserConstants.JSON_PARSER);
                JsonNode root = (JsonNode) parser.unmarshallString(jsonConfiguration);
                Configuration configuration = null;

                for (int i = 0; i < root.size(); i++) {

                    JsonNode config = root.get(i);

                    String condition = config.get("condition").getValueAsText();
                    int configType = config.get("configType").getIntValue();
                    String description = config.get("description").getValueAsText();
                    String jsonConfig = config.get("jsonConfig").getValueAsText();

                    configuration = new Configuration();
                    configuration.setMock(service);
                    if (configType == 1) {
                        configuration.setCondition(condition);
                        configuration.setDescription(description);
                        configuration.setType(configType);
                        configuration.setItemRenderer(jsonConfig);
                    }

                    service.getConfigurations().add(configuration);
                }

                selectedProject.getServices().add(service);
                getInternalDatasource().persist(service);

            }

        } else if ("projectDetails".equals(method)) {
            if (selectedProject != null) {
                List<String> endpoints = new ArrayList<String>();
                for (MockService service : selectedProject.getServices()) {
                    endpoints.add(service.getEndpoint());
                }
                addReturnParameter(ProjectConstants.PROJECT_ENDPOINT, endpoints);
            }
        } else if ("endpointDetails".equals(method)) {
            MockService service = null;
            for (MockService serviceElement : selectedProject.getServices()) {
                if (serviceElement.getEndpoint().equals(endpoint)) {
                    service = serviceElement;
                    break;
                }
            }

            if (service != null) {
                addReturnParameter(ProjectConstants.RESPONSE_TYPE, service.getType());
                List<Map<String,String>> configurationMap = new ArrayList<Map<String,String>>(service.getConfigurations().size());

                for (Configuration config : service.getConfigurations()) {
                    configurationMap.add(config.getMappedConfiguration());
                }


                addReturnParameter(ProjectConstants.CONFIGURATION, configurationMap);
            }
        }

        return getReturnMap();
    }

    @Override
    public String getName() {
        return "Project controller";
    }
}
